home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / listings / v_12_09 / single2 / cmostr.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-07  |  9.8 KB  |  390 lines

  1. //    cmostr.cpp
  2. //    modification of Microsoft Foundation Class code supporting CString, to make use
  3. //    of CMemoryObject base class.
  4.  
  5. // This is a part of the Microsoft Foundation Classes C++ library. 
  6. // Copyright (C) 1992 Microsoft Corporation 
  7. // All rights reserved. 
  8. //  
  9. // This source code is only intended as a supplement to the 
  10. // Microsoft Foundation Classes Reference and Microsoft 
  11. // QuickHelp and/or WinHelp documentation provided with the library. 
  12. // See these sources for detailed information regarding the 
  13. // Microsoft Foundation Classes product. 
  14.  
  15. #include "stdafx.h"
  16. #include <limits.h>
  17. #include "cmostr.h"
  18. #include "mobject.h"
  19.  
  20. #ifdef _DEBUG
  21. #undef THIS_FILE
  22. static char BASED_CODE THIS_FILE[] = __FILE__;
  23. #endif
  24.  
  25. #define new DEBUG_NEW
  26.  
  27. /////////////////////////////////////////////////////////////////////////////
  28. // static class data, special inlines
  29.  
  30. char FAR CMOStringChNil = '\0';
  31.  
  32. // For an empty string, m_???Data will point here
  33. // (note: avoids a lot of NULL pointer tests when we call standard
  34. //  C runtime libraries
  35.  
  36. extern const CMOString afxEmptyString;   
  37.         // for creating empty key strings
  38. const CMOString afxEmptyString;
  39.  
  40. void CMOString::Init()
  41. {
  42.     m_nDataLength = m_nAllocLength = 0;
  43.     m_pchData = (char FAR *)&CMOStringChNil;
  44. }
  45.  
  46. static void NEAR PASCAL SafeDelete(char FAR * pch)
  47. {
  48.     if (pch != NULL && pch != (char FAR *)&CMOStringChNil)
  49. //        delete [] pch;
  50.         MemoryObject::ReturnBlock (pch);
  51. }
  52.  
  53. //////////////////////////////////////////////////////////////////////////////
  54. // Construction/Destruction
  55.  
  56. CMOString::CMOString()
  57. {
  58.     Init();
  59. }
  60.  
  61. CMOString::CMOString(const CMOString& stringSrc)
  62. {
  63.     // if constructing a CMOString from another CMOString, we make a copy of the
  64.     // original string data to enforce value semantics (i.e. each string
  65.     // gets a copy of it's own
  66.  
  67.     stringSrc.AllocCopy(*this, stringSrc.m_nDataLength, 0, 0);
  68. }
  69.  
  70. void CMOString::AllocBuffer(int nLen)
  71.  // always allocate one extra character for '\0' termination
  72.  // assumes [optimistically] that data length will equal allocation length
  73. {
  74.     ASSERT(nLen >= 0);
  75.     ASSERT(nLen <= INT_MAX - 1);    // max size (enough room for 1 extra)
  76.  
  77.     if (nLen == 0)
  78.     {
  79.         Init();
  80.     }
  81.     else
  82.     {   
  83. //        typedef char FAR fc;
  84. //        m_pchData = new fc;
  85. //        char FAR * tmp, * tmp_a;
  86. //        tmp = new fc;
  87. //        tmp_a = new fc [nLen+1]; 
  88. //        m_pchData = new fc [nLen+1];       // may throw an exception
  89.         m_pchData = (char FAR *) MemoryObject::AllocateBlock (nLen + 1);       // may throw an exception
  90.         m_pchData[nLen] = '\0';
  91.         m_nDataLength = nLen;
  92.         m_nAllocLength = nLen;
  93.     }
  94. }
  95.  
  96. void CMOString::Empty()
  97. {
  98.     SafeDelete(m_pchData);
  99.     Init();
  100.     ASSERT(m_nDataLength == 0);
  101.     ASSERT(m_nAllocLength == 0);
  102. }
  103.  
  104. CMOString::~CMOString()
  105.  //  free any attached data
  106. {
  107.     SafeDelete(m_pchData);
  108. }
  109.  
  110. //////////////////////////////////////////////////////////////////////////////
  111. // Helpers for the rest of the implementation
  112.  
  113. static inline int SafeStrlen(const char FAR * psz)
  114.     { return (psz == NULL) ? NULL : _fstrlen(psz); }
  115.  
  116. void CMOString::AllocCopy(CMOString& dest, int nCopyLen, int nCopyIndex,
  117.      int nExtraLen) const
  118. {
  119.     // will clone the data attached to this string
  120.     // allocating 'nExtraLen' characters
  121.     // Places results in uninitialized string 'dest'
  122.     // Will copy the part or all of original data to start of new string
  123.  
  124.     int nNewLen = nCopyLen + nExtraLen;
  125.  
  126.     if (nNewLen == 0)
  127.     {
  128.         dest.Init();
  129.     }
  130.     else
  131.     {
  132.         dest.AllocBuffer(nNewLen);
  133.         _fmemcpy(dest.m_pchData, &m_pchData[nCopyIndex], nCopyLen);
  134.     }
  135. }
  136.  
  137. //////////////////////////////////////////////////////////////////////////////
  138. // More sophisticated construction
  139.  
  140. CMOString::CMOString(const char FAR * psz)
  141. {
  142.     int nLen;
  143.     if ((nLen = SafeStrlen(psz)) == 0)
  144.         Init();
  145.     else
  146.     {
  147.         AllocBuffer(nLen);
  148.         _fmemcpy(m_pchData, psz, nLen);
  149.     }
  150. }
  151.  
  152. //////////////////////////////////////////////////////////////////////////////
  153. // Diagnostic support
  154.  
  155. #ifdef _DEBUG 
  156.  
  157. CDumpContext&
  158. AFXAPI operator <<(CDumpContext& dc, const CMOString& string)
  159. {
  160.     dc << string.m_pchData;
  161.     return dc;
  162. }
  163.  
  164. #endif //_DEBUG
  165.  
  166. //////////////////////////////////////////////////////////////////////////////
  167. // Assignment operators
  168. //  All assign a new value to the string
  169. //      (a) first see if the buffer is big enough
  170. //      (b) if enough room, copy on top of old buffer, set size and type
  171. //      (c) otherwise free old string data, and create a new one
  172. //
  173. //  All routines return the new string (but as a 'const CMOString&' so that
  174. //      assigning it again will cause a copy, eg: s1 = s2 = "hi there".
  175. //
  176.  
  177. void CMOString::AssignCopy(int nSrcLen, const char FAR * pszSrcData)
  178. {
  179.     // check if it will fit
  180.     if (nSrcLen > m_nAllocLength)
  181.     {
  182.         // it won't fit, allocate another one
  183.         Empty();
  184.         AllocBuffer(nSrcLen);
  185.     }
  186.     if (nSrcLen != 0)
  187.         _fmemcpy(m_pchData, pszSrcData, nSrcLen);
  188.     m_nDataLength = nSrcLen;
  189.     m_pchData[nSrcLen] = '\0';
  190. }
  191.  
  192. const CMOString&
  193. CMOString::operator =(const CMOString& stringSrc)
  194. {
  195.     AssignCopy(stringSrc.m_nDataLength, stringSrc.m_pchData);
  196.     return *this;
  197. }
  198.  
  199. const CMOString&
  200. CMOString::operator =(const char FAR * psz)
  201. {
  202.     AssignCopy(SafeStrlen(psz), psz);
  203.     return *this;
  204. }
  205.  
  206.  
  207. //////////////////////////////////////////////////////////////////////////////
  208. // concatenation
  209.  
  210. // NOTE: "operator +" is done as friend functions for simplicity
  211. //      There are three variants:
  212. //          CMOString + CMOString
  213. // and for ? = char, const char FAR *
  214. //          CMOString + ?
  215. //          ? + CMOString
  216.  
  217. void
  218. CMOString::ConcatCopy(int nSrc1Len, const char FAR * pszSrc1Data,
  219.         int nSrc2Len, const char FAR * pszSrc2Data)
  220. {
  221.   // -- master concatenation routine
  222.   // Concatenate two sources
  223.   // -- assume that 'this' is a new CMOString object
  224.  
  225.     int nNewLen = nSrc1Len + nSrc2Len;
  226.     AllocBuffer(nNewLen);
  227.     _fmemcpy(m_pchData, pszSrc1Data, nSrc1Len);
  228.     _fmemcpy(&m_pchData[nSrc1Len], pszSrc2Data, nSrc2Len);
  229. }
  230.  
  231. CMOString
  232. AFXAPI operator +(const CMOString& string1, const CMOString& string2)
  233. {
  234.     CMOString s;
  235.     s.ConcatCopy(string1.m_nDataLength, string1.m_pchData,
  236.         string2.m_nDataLength, string2.m_pchData);
  237.     return s;
  238. }
  239.  
  240. CMOString
  241. AFXAPI operator +(const CMOString& string, const char FAR * psz)
  242. {
  243.     CMOString s;
  244.     s.ConcatCopy(string.m_nDataLength, string.m_pchData, SafeStrlen(psz), psz);
  245.     return s;
  246. }
  247.  
  248.  
  249. CMOString
  250. AFXAPI operator +(const char FAR * psz, const CMOString& string)
  251. {
  252.     CMOString s;
  253.     s.ConcatCopy(SafeStrlen(psz), psz, string.m_nDataLength, string.m_pchData);
  254.     return s;
  255. }
  256.  
  257. //////////////////////////////////////////////////////////////////////////////
  258. // concatenate in place
  259.  
  260. void
  261. CMOString::ConcatInPlace(int nSrcLen, const char FAR * pszSrcData)
  262. {
  263.     //  -- the main routine for += operators
  264.  
  265.     // if the buffer is too small, or we have a width mis-match, just
  266.     //   allocate a new buffer (slow but sure)
  267.     if (m_nDataLength + nSrcLen > m_nAllocLength)
  268.     {
  269.         // we have to grow the buffer, use the Concat in place routine
  270.         char FAR * pszOldData = m_pchData;
  271.         ConcatCopy(m_nDataLength, pszOldData, nSrcLen, pszSrcData);
  272.         ASSERT(pszOldData != NULL);
  273.         SafeDelete(pszOldData);
  274.     }
  275.     else
  276.     {
  277.         // fast concatenation when buffer big enough
  278.         _fmemcpy(&m_pchData[m_nDataLength], pszSrcData, nSrcLen);
  279.         m_nDataLength += nSrcLen;
  280.     }
  281.     ASSERT(m_nDataLength <= m_nAllocLength);
  282.     m_pchData[m_nDataLength] = '\0';
  283. }
  284.  
  285. const CMOString&
  286. CMOString::operator +=(const char FAR * psz)
  287. {
  288.     ConcatInPlace(SafeStrlen(psz), psz);
  289.     return *this;
  290. }
  291.  
  292. const CMOString&
  293. CMOString::operator +=(char ch)
  294. {
  295.     ConcatInPlace(1, &ch);
  296.     return *this;
  297. }
  298.  
  299. const CMOString&
  300. CMOString::operator +=(const CMOString& string)
  301. {
  302.     ConcatInPlace(string.m_nDataLength, string.m_pchData);
  303.     return *this;
  304. }
  305.  
  306.  
  307. ///////////////////////////////////////////////////////////////////////////////
  308. // Advanced direct buffer access
  309.  
  310. char FAR * CMOString::GetBuffer(int nMinBufLength)
  311. {
  312.     ASSERT(nMinBufLength >= 0);
  313.  
  314.     if (nMinBufLength > m_nAllocLength)
  315.     {
  316.         // we have to grow the buffer
  317.         char FAR * pszOldData = m_pchData;
  318.         int nOldLen = m_nDataLength;        // AllocBuffer will tromp it
  319.  
  320.         AllocBuffer(nMinBufLength);
  321.         _fmemcpy(m_pchData, pszOldData, nOldLen);
  322.         m_nDataLength = nOldLen;
  323.         m_pchData[m_nDataLength] = '\0';
  324.  
  325.         SafeDelete(pszOldData);
  326.     }
  327.  
  328.     // return a pointer to the character storage for this string
  329.     ASSERT(m_pchData != NULL);
  330.     return m_pchData;
  331. }
  332.  
  333. void CMOString::ReleaseBuffer(int nNewLength)
  334. {
  335.     if (nNewLength == -1)
  336.         nNewLength = _fstrlen(m_pchData); // zero terminated
  337.  
  338.     ASSERT(nNewLength <= m_nAllocLength);
  339.     m_nDataLength = nNewLength;
  340.     m_pchData[m_nDataLength] = '\0';
  341. }
  342.  
  343. char FAR * CMOString::GetBufferSetLength(int nNewLength)
  344. {
  345.     ASSERT(nNewLength >= 0);
  346.  
  347.     GetBuffer(nNewLength);
  348.     m_nDataLength = nNewLength;
  349.     m_pchData[m_nDataLength] = '\0';
  350.     return m_pchData;
  351. }
  352.  
  353. ///////////////////////////////////////////////////////////////////////////////
  354. // Commonly used routines (rarely used routines in STREX.CPP)
  355.  
  356. int CMOString::Find(char ch) const
  357. {
  358.     // find a single character (strchr)
  359.     char FAR * psz = _fstrchr(m_pchData, ch);
  360.     return (psz == NULL) ? -1 : (int)(psz - m_pchData);
  361. }
  362.  
  363. int CMOString::FindOneOf(const char FAR * pszCharSet) const
  364. {
  365.     ASSERT(pszCharSet != NULL);
  366.     char FAR * psz = (char FAR *) _fstrpbrk(m_pchData, pszCharSet);
  367.     return (psz == NULL) ? -1 : (int)(psz - m_pchData);
  368. }
  369.  
  370. ///////////////////////////////////////////////////////////////////////////////
  371. // Additional constructors for far string data
  372.  
  373. #if defined(_NEARDATA) && defined (qq_zz_aa_dd_)
  374. CMOString::CMOString(LPCSTR lpsz)
  375. {
  376.     int nLen;
  377.     if (lpsz == NULL || (nLen = lstrlen(lpsz)) == 0)
  378.     {
  379.         Init();
  380.     }
  381.     else
  382.     {
  383.         AllocBuffer(nLen);
  384.         _fmemcpy(m_pchData, lpsz, nLen);
  385.     }
  386. }
  387. #endif //_NEARDATA
  388.  
  389. ///////////////////////////////////////////////////////////////////////////////
  390.